/*
 * Copyright (c) 2024 Huawei Technologies Co., Ltd.
 * openFuyao is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

package requestutils

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestPrepareUserManagementRequestURL(t *testing.T) {
	// 定义测试用例
	tests := []struct {
		clusterName string
		suffix      string
		expectedURL string
	}{
		{
			clusterName: "cluster1", suffix: "/users/list",
			expectedURL: "https://console-service.openfuyao-system.svc.cluster.local:80/clusters/" +
				"cluster1/rest/user/v1/users/list",
		},
		{
			clusterName: "cluster2", suffix: "/users/details",
			expectedURL: "https://console-service.openfuyao-system.svc.cluster.local:80/clusters/" +
				"cluster2/rest/user/v1/users/details",
		},
		{
			clusterName: "prod-cluster", suffix: "/users/delete",
			expectedURL: "https://console-service.openfuyao-system.svc.cluster.local:80/clusters" +
				"/prod-cluster/rest/user/v1/users/delete",
		},
		{
			clusterName: "dev-cluster", suffix: "/roles/assign",
			expectedURL: "https://console-service.openfuyao-system.svc.cluster.local:80/clusters" +
				"/dev-cluster/rest/user/v1/roles/assign",
		},
	}

	// 遍历每个测试用例
	for _, tt := range tests {
		t.Run(fmt.Sprintf("clusterName=%s, suffix=%s", tt.clusterName, tt.suffix), func(t *testing.T) {
			// 调用被测试的函数
			resultURL := PrepareUserMgmtRequestURL(tt.clusterName, tt.suffix)

			// 使用 assert.Equal 断言实际结果与预期结果是否相同
			assert.Equal(t, tt.expectedURL, resultURL, "they should be equal")
		})
	}
}

func TestPrepareK8sResourceRequestURL(t *testing.T) {
	// 定义测试用例
	tests := []struct {
		clusterName string
		suffix      string
		expectedURL string
	}{
		{
			clusterName: "cluster1",
			suffix:      "/pods/list",
			expectedURL: "https://console-service.openfuyao-system.svc.cluster.local:80/clusters/cluster1/api/kubernetes/pods/list",
		},
		{
			clusterName: "cluster2",
			suffix:      "/deployments/details",
			expectedURL: "https://console-service.openfuyao-system.svc.cluster.local:80/clusters/cluster2/api/kubernetes/deployments/details",
		},
		{
			clusterName: "prod-cluster",
			suffix:      "/services/delete",
			expectedURL: "https://console-service.openfuyao-system.svc.cluster.local:80/clusters/prod-cluster/api/kubernetes/services/delete",
		},
	}

	// 遍历测试用例
	for _, tt := range tests {
		t.Run(fmt.Sprintf("clusterName=%s, suffix=%s", tt.clusterName, tt.suffix), func(t *testing.T) {
			// 调用被测试的函数
			resultURL := PrepareK8sResourceRequestURL(tt.clusterName, tt.suffix)

			// 使用 assert.Equal 断言实际结果与预期结果是否相同
			assert.Equal(t, tt.expectedURL, resultURL, "they should be equal")
		})
	}
}

func TestPrepareMultiClusterRequestURL(t *testing.T) {
	// 定义测试用例
	tests := []struct {
		suffix      string
		expectedURL string
	}{
		{
			suffix:      "/clusters/list",
			expectedURL: "https://console-service.openfuyao-system.svc.cluster.local:80/rest/multicluster/v1beta1/clusters/list",
		},
		{
			suffix:      "/nodes/details",
			expectedURL: "https://console-service.openfuyao-system.svc.cluster.local:80/rest/multicluster/v1beta1/nodes/details",
		},
		{
			suffix:      "/resources/delete",
			expectedURL: "https://console-service.openfuyao-system.svc.cluster.local:80/rest/multicluster/v1beta1/resources/delete",
		},
	}

	// 遍历测试用例
	for _, tt := range tests {
		t.Run(fmt.Sprintf("suffix=%s", tt.suffix), func(t *testing.T) {
			// 调用被测试的函数
			resultURL := PrepareMultiClusterRequestURL(tt.suffix)

			// 使用 assert.Equal 断言实际结果与预期结果是否相同
			assert.Equal(t, tt.expectedURL, resultURL, "they should be equal")
		})
	}
}

// 模拟的工具日志函数
var logInfoCalled bool
var logErrorCalled bool

func LogInfo(message string, args ...interface{}) {
	logInfoCalled = true
}

func LogError(message string, args ...interface{}) {
	logErrorCalled = true
}
func TestAddAuthorizationHeader(t *testing.T) {
	// 测试数据
	tests := []struct {
		name                  string
		reqHeaders            map[string]string
		expectedExtReqHeaders map[string]string
		expectLogError        bool
	}{
		{
			name: "Both Authorization and OpenFuyaoAuth headers present",
			reqHeaders: map[string]string{
				"Authorization": "Bearer test-token",
			},
			expectedExtReqHeaders: map[string]string{
				"Authorization": "Bearer test-token",
			},
			expectLogError: false,
		},
	}

	// 遍历每个测试用例
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// 初始化请求和外部请求
			req := &http.Request{
				Header: make(http.Header),
			}
			extReq := &http.Request{
				Header: make(http.Header),
			}

			// 设置请求头
			for key, value := range tt.reqHeaders {
				req.Header.Set(key, value)
			}

			// 调用被测试的函数
			addAuthorizationHeader(req, extReq)

			// 验证 extReq 是否包含预期的头信息
			for key, expectedValue := range tt.expectedExtReqHeaders {
				actualValue := extReq.Header.Get(key)
				assert.Equal(t, expectedValue, actualValue, "Expected header value for %s", key)
			}

			// 验证是否调用了 LogError
			if tt.expectLogError {
				assert.True(t, logErrorCalled, "Expected LogError to be called")
			} else {
				assert.False(t, logErrorCalled, "Expected LogError not to be called")
			}

			// 重置日志标记
			logInfoCalled = false
			logErrorCalled = false
		})
	}
}

type ApiResponse struct {
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data"`
}

func TestDoUserManagementRequest(t *testing.T) {
	// 创建模拟的 HTTP 服务器
	mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 模拟返回的 API 响应
		mockResponse := ApiResponse{
			Code: 200,
			Msg:  "Success",
			Data: map[string]string{"key": "value"},
		}
		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(mockResponse)
	}))
	defer mockServer.Close()

	// 定义测试用例
	tests := []struct {
		name          string
		method        string
		reqBodyBytes  []byte
		expectedBody  ApiResponse
		expectedError bool
	}{
		{
			name:          "GET request success",
			method:        "GET",
			reqBodyBytes:  nil,
			expectedBody:  ApiResponse{Code: 200, Msg: "Success", Data: map[string]interface{}{"key": "value"}},
			expectedError: false,
		},
		{
			name:          "POST request with body",
			method:        "POST",
			reqBodyBytes:  []byte(`{"test":"data"}`),
			expectedBody:  ApiResponse{Code: 200, Msg: "Success", Data: map[string]interface{}{"key": "value"}},
			expectedError: false,
		},
	}

	// 遍历测试用例
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// 创建模拟的原始请求
			oriReq, _ := http.NewRequest("GET", mockServer.URL, nil)
			oriReq.Header.Set("Authorization", "Bearer test-token")

			// 调用被测试的函数
			apiResponse, err := DoUserManagementRequest(mockServer.URL, tt.method, oriReq, tt.reqBodyBytes)

			// 验证是否有预期的错误
			if tt.expectedError {
				assert.NotNil(t, err)
			} else {
				assert.Nil(t, err)
			}

			// 验证响应体内容
			assert.Equal(t, tt.expectedBody.Code, apiResponse.Code)
			assert.Equal(t, tt.expectedBody.Msg, apiResponse.Msg)
			assert.Equal(t, tt.expectedBody.Data, apiResponse.Data)
		})
	}
}

func TestDoRequestWithMaxRetries(t *testing.T) {
	// 模拟 HTTP 服务器
	mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 模拟重试逻辑
		if r.Header.Get("Retry-Attempt") == "" {
			w.Header().Set("Retry-Attempt", "1")
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprintln(w, "Internal Server Error")
			return
		}
		w.WriteHeader(http.StatusOK)
		fmt.Fprintln(w, `{"key":"value"}`)
	}))
	defer mockServer.Close()

	// 定义测试用例
	tests := []struct {
		name          string
		method        string
		reqBodyBytes  []byte
		maxAttempts   int
		expectedCode  int
		expectedBody  string
		expectedError bool
	}{
		{
			name:          "Fail after max retries",
			method:        "GET",
			reqBodyBytes:  nil,
			maxAttempts:   1,
			expectedCode:  http.StatusInternalServerError,
			expectedBody:  "",
			expectedError: true,
		},
	}

	// 遍历测试用例
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// 创建模拟的原始请求
			oriReq, _ := http.NewRequest("GET", mockServer.URL, nil)
			oriReq.Header.Set("Authorization", "Bearer test-token")

			// 调用被测试的函数
			statusCode, body, err := DoRequestWithMaxRetries(mockServer.URL, tt.method, oriReq,
				tt.reqBodyBytes, tt.maxAttempts)

			// 验证响应状态码和响应体
			assert.Equal(t, tt.expectedCode, statusCode)
			assert.Equal(t, tt.expectedBody, string(body))

			// 验证是否有预期的错误
			if tt.expectedError {
				assert.NotNil(t, err)
			} else {
				assert.Nil(t, err)
			}
		})
	}
}
